<?php


namespace app\middleware;


use app\admin\system\logic\AdminLogic;
use common\annotation\OperationLog;
use core\constants\QueueKey;
use core\utils\MqUtil;
use core\utils\RandomUtil;
use ReflectionClass;
use support\Log;
use Throwable;
use Webman\Http\Request;
use Webman\Http\Response;
use Webman\MiddlewareInterface;

class OperationLogMiddleware implements MiddlewareInterface
{

    private int $start_time;

    public function process(Request $request, callable $handler): Response
    {
        // 通过反射获取控制器哪些方法不需要登录
        $controller = new ReflectionClass($request->controller);
        $controllerAttributes = $controller->getAttributes(OperationLog::class);
        $method = $controller->getMethod($request->action);
        $actionAttributes = $method->getAttributes(OperationLog::class);
        $this->start_time = time();
        $response = $handler($request);
        if ($actionAttributes) {
            $obj = $actionAttributes[0]->newInstance();
            $module = $obj->module;
            $type = $obj->type;
            if ($controllerAttributes) {
                $contrObj = $controllerAttributes[0]->newInstance();
                $module = $contrObj->module;
            }
            if (!$type) {
                if (str_contains($request->action, "add")) {
                    $type = OperationLog::ADD;
                }
                if (str_contains($request->action, "update") || str_contains($request->action, "changeStatus")) {
                    $type = OperationLog::UPDATE;
                }
                if (str_contains($request->action, "remove")) {
                    $type = OperationLog::REMOVE;
                }

            }
            try {
                $this->writeLog($request, $module, $obj->action, $type);
            } catch (Throwable $exception) {
                Log::error($exception->getTraceAsString());
            }
        }
        return $response;
    }

    private function writeLog(Request $request, $module, $action, $type)
    {
//        $request_method = $request->controller . '::' . $request->action;
//        if ('::' === $request_method) {
//            $request_method = $request->path();
//        }
        $finishTime = microtime(true);
        $costTime = $finishTime - $this->start_time;
        $user = AdminLogic::getCurrentLogicAdmin(request()->uid);
        $data = [
            "trace_id" => RandomUtil::UUID(),
            "user_id" => $request->uid,
            "user_type" => $request->user_type,
            "module" => $module,
            "name" => $action,
            "type" => $type,
            "content" => json_encode($request->all(), JSON_UNESCAPED_UNICODE),
            "request_url" => $request->uri(),
            "user_ip" => $request->getRealIp(),
            "user_agent" => $request->header('user-agent'),
            'start_time' => date('Y-m-d H:i:s.', (int)$this->start_time) . substr($this->start_time, 11),
            'duration' => $costTime * 1000,
            'creator' => $user['nickname'] ?? "",
            "request_method" => $request->method(),
        ];
        MqUtil::send(QueueKey::OPERATION_LOG, $data);
    }
}